package stream_function;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamFunctionDemo {

    private static class Person {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("jack", 30));
        people.add(new Person("rose", 28));
        people.add(new Person("tom", 20));

        // 1. Function是一个功能型的接口，用于将一种类型的数据转化为另外一种类型的数据
        // 1.1 匿名内部类写法
        List<String> names = people.stream().map(new Function<Person, String>() {
            @Override
            public String apply(Person person) {
                return person.getName();
            }
        }).collect(Collectors.toList());
        // 1.2 lambda写法
        names = people.stream().map(Person::getName).collect(Collectors.toList());
        System.out.println(names);

        // 2. Consumer是一个消费型的接口
        // 2.1 匿名内部类写法
        people.forEach(new Consumer<Person>() {
            @Override
            public void accept(Person person) {
                System.out.println(person.getName());
            }
        });
        // 2.2 lambda写法
        people.forEach(person -> System.out.println(person.getName()));

        // 3. Supplier
        // 3.1 匿名内部类写法
        // generate返回无限连续流，为了限制流中元素的数量，我们可以使用Stream.limit方法
        Stream.generate(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(10);
            }
        }).limit(10).forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });
        // 3.2 lambda写法
        Stream.generate(() -> new Random().nextInt(10)).limit(10).forEach(System.out::println);

        // 4. Predictor
        // 4.1 匿名内部类写法
        List<Person> midAged = people.stream().filter(new Predicate<Person>() {
            @Override
            public boolean test(Person person) {
                return person.getAge() >= 30;
            }
        }).collect(Collectors.toList());
        // 4.2 lambda写法
        midAged = people.stream().filter(person -> person.getAge() >= 30).collect(Collectors.toList());
        System.out.println(midAged);

        // 5. groupingBy
        // 5.1 匿名内部类写法
        Map<Integer, List<Person>> ageMap = people.stream().collect(Collectors.groupingBy(new Function<Person, Integer>() {
            @Override
            public Integer apply(Person person) {
                return person.getAge();
            }
        }));
        // 5.2 lambda写法
        ageMap = people.stream().collect(Collectors.groupingBy(Person::getAge));
        System.out.println(ageMap);
    }
}
